import { downloadFileLocal } from "../../helper";
import { Uploader } from "./uploader";
import { getHeaderTicketKey } from "./bd/index";
import { PlatformClient } from "../platformClient";
import { ProxyRequest } from "../proxyRequest";
import { PlatformHeaderTicketTimeoutError, PlatformUserAccountExpiredError, ProxyRequestExceptionError } from "../../errors";

export class Client extends PlatformClient {
  static BASE_URL = 'https://creator.douyin.com'

  constructor(accountUser) {
    super()

    this.accountUser = accountUser;
    this.csrfTokenMap = {}
  }

  getUserInfo() {
    return this.request({
      url: '/web/api/media/user/info/',
    })
  }

  async uploadVideo(urls) {
    urls = [].concat(urls)
    let filePaths = await Promise.all(urls.map(url => downloadFileLocal(url)))
    filePaths = filePaths.filter(filePath => !!filePath)

    const authRes = await this.getUploadConfig();
    const uploader = new Uploader({
      ...authRes.auth,
      ThirdId: this.accountUser.thirdId,
      UserAgent: this.accountUser.userAgent
    })

    const CONCURRENT_UPLOADS = 3; // 最大并发数
    const results = [];
    
    for (let i = 0; i < filePaths.length; i += CONCURRENT_UPLOADS) {
      const batch = filePaths.slice(i, i + CONCURRENT_UPLOADS);
      const batchPromises = batch.map(async (filePath) => {
        try {
          const videoId = await uploader.uploadVideo(filePath);

          return {
            filePath,
            videoId,
            success: true
          };
        } catch (error) {
          console.error(`上传视频失败: ${filePath}`, error);
          return {
            filePath,
            error: error.message,
            success: false
          };
        }
      });

      const batchResults = await Promise.all(batchPromises);
      results.push(...batchResults);
    }

    const successResult = results.filter(r => r.success)

    // 统计上传结果
    console.log(`上传完成: 成功 ${successResult.length}/${filePaths.length}`, successResult);

    // 返回成功的结果
    return successResult;
  }

  async getUploadConfig() {
    let { data } = await this.request({
      url: '/web/api/media/upload/auth/v5/',
      method: 'GET'
    })

    if(data.status_code === 0){
      data.auth = JSON.parse(data.auth)
    } else {
      throw new Error('获取上传配置失败')
    }
    
    return data
  }

  //查询账号是否存在带货模式+团购
  async lifeVideoApiPostPermission(params = {}){
    const queryArr = {
      from_webapp: params.from_webapp || 1,
      is_image_album_style: params.is_image_album_style || 0,
      options: '{}',
      cookie_enabled: true,
      screen_width: 1920,
      screen_height: 1080,
      browser_language: 'zh-CN',
      timezone_name: 'Asia/Shanghai',
      aid: 1128
    };

    const { data } = await this.request({
      url: '/aweme/v1/life/video_api/post/permission/',
      method: 'GET',
      params: queryArr,
      headers: {
        'referer': 'https://creator.douyin.com/creator-micro/content/publish?enter_from=publish_page',
        'content-type': 'application/json; charset=utf-8'
      }
    });

    if (data.status_code !== 0){
      throw new Error(data.status_msg)
    }

    return data
  }

  async userAnchorCheck(params = {}){
    if (!params.applet_id) {
      return [];
    }

    const queryArr = {
      item_type: params.item_type || 1,
      select_anchor: params.select_anchor || 2,
      applet_id: params.applet_id,
      cookie_enabled: 'true',
      screen_width: 1920,
      screen_height: 1080,
      browser_language: 'zh-CN',
      timezone_name: 'Asia/Shanghai',
      aid: 1128
    };

    const { data } = await this.request({
      url: '/web/api/media/user/anchor/check',
      method: 'GET',
      params: queryArr,
      headers: {
        'authority': 'creator.douyin.com',
        'referer': 'https://creator.douyin.com/creator-micro/content/publish?enter_from=publish_page',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36'
      }
    })

    if (data.status_code !== 0){
      throw new Error(data.status_msg)
    }

    return data
  }

  async searchChallengeSug(keyword){
    const { data } = await this.request({
      url: '/aweme/v1/search/challengesug/',
      method: 'GET',
      params: {
        aid: 2906,
        source: 'challenge_create',
        keyword
      },
      headers: {
        Referer: 'https://creator.douyin.com/creator-micro/content/publish-media/image-text?enter_from=publish_page'
      }
    })

    if (data.status_code !== 0){
      throw new Error(data.status_msg)
    }

    return data
  }

  async getCsrfToken(url) {
    if (this.csrfTokenMap[url]){
      return this.csrfTokenMap[url]
    }

    const response = await this.request({
      url,
      method: 'HEAD',
      headers: {
        'x-secsdk-csrf-request': '1',
        'x-secsdk-csrf-version': '1.2.7'
      }
    });

    if (! response.headers['x-ware-csrf-token']){
      throw new Error('获取发布csrf-token失败:' + JSON.stringify(response.headers))
    }

    this.csrfTokenMap[url] = response.headers['x-ware-csrf-token'].split(',')[1];

    return this.csrfTokenMap[url]
  }

  async getPublicVideoV2(publishData){
    const headerTicket = await this.getHeaderTicketKey('video');
    
    const publishUrl = '/web/api/media/aweme/create_v2/'
    const csrfToken = await this.getCsrfToken(publishUrl)

    let headers = {
      ...headerTicket,
      'Content-Type': 'application/json',
      'X-Secsdk-Csrf-Token': csrfToken,
      Referer: 'https://creator.douyin.com/creator-micro/content/post/video?enter_from=publish_page',
    }

    let { data } = await this.request({
      url: publishUrl,
      method: 'POST',
      params: {
        read_aid: 2906,
        cookie_enabled: true,
        screen_width: 1920,
        screen_height: 1080,
        browser_language: 'zh-CN',
        timezone_name: 'Asia/Shanghai',
      },
      headers,
      data: publishData
    })

    if (data.status_code !== 0){
      throw new Error(data.status_msg)
    }

    if (! data.item_id){
      throw new Error('发布失败:' + JSON.stringify(data))
    }

    return {
      aweme: data
    }
  }

  async getHeaderTicketKeyRetry(params){
    let response 

    try {
      response = await getHeaderTicketKey(params)
    } catch (e){
      const errorMessage = e.message.toLowerCase();

      console.log(`Douyin:HeaderTicketKey:ProxyRequest:Exception-----> ${errorMessage}`)

      if (
        errorMessage.includes('err_cert_common_name_invalid')
        || errorMessage.includes('err_tunnel_connection_failed')
      ) {
        throw new ProxyRequestExceptionError(e.message);
      }
      
      throw e;
    }

    return response
  }
  
  async getHeaderTicketKey(type = 'tuwen'){
    let proxy = ''

    if (this.clientRequest instanceof ProxyRequest){
      const result = await this.clientRequest.getProxyInfo(true)
      console.log('获取代理信息', 'getHeaderTicketKey', result)
      proxy = `${result.protocol}${result.user}:${result.password}@${result.ip}:${result.port}`;
    }

    const pRetry = (...args) => import('p-retry').then(({default: retry}) => retry(...args));

    return pRetry(async () => {
      const controller = new AbortController();
      
      return Promise.race([
        new Promise((_, reject) => {
          setTimeout(() => {
            controller.abort();
            reject(new PlatformHeaderTicketTimeoutError('获取 ticket 超时'))
          }, 2 * 60000);
        }),
        this.getHeaderTicketKeyRetry({
          cookies: this.accountUser.cookie,
          user_agent: this.accountUser.userAgent,
          localdata: this.accountUser.getThirdParam('localdata') || [],
          third_id: this.accountUser.thirdId,
          proxy,
          type,
          signal: controller.signal  // 传入信号
        })
      ]);
    }, {
      retries: 4,
      shouldRetry: (error) => error instanceof PlatformHeaderTicketTimeoutError || error instanceof ProxyRequestExceptionError,
      onFailedAttempt: async (error) => {
        console.log(`获取 ticket 失败，剩余重试次数: ${error.retriesLeft}, 代理信息为: ${proxy}, 错误信息为: ${error.message}`);

        if(
          error instanceof PlatformHeaderTicketTimeoutError
          || error instanceof ProxyRequestExceptionError
        ){
          const result = await this.clientRequest.getProxyInfo(true)
          console.log('重新获取代理信息', 'getHeaderTicketKey', result)
          proxy = `${result.protocol}${result.user}:${result.password}@${result.ip}:${result.port}`;
        }
      }
    });
  }

  async request(options) {
    options['method'] = options['method'] || 'GET'

    options['headers'] = Object.assign({}, {
      'Cookie': this.accountUser.cookie,
      'User-Agent': this.accountUser.userAgent,
      'Referer': Client.BASE_URL
    }, options['headers'] || {})

    let response

    try {
      response = await this.clientRequest.request({
        baseURL: Client.BASE_URL,
       ...options
      })
    } catch (e){
      const errorMessage = e.message.toLowerCase();

      console.log(`Douyin:Request:Exception-----> ${errorMessage}`, options)
      
      if (
        errorMessage.includes('request failed with status code 403')
      ) {
        throw new PlatformUserAccountExpiredError('账号已过期');
      }

      throw e
    }

    return response
  }
}